<?php

namespace encrypt\classes;

/**
 * RSA加密解密类
 * Class RSA
 * @package encrypt\classes
 */
class RSA implements \encrypt\RSA
{

    /**
     * 使用公钥操作
     */
    const USE_PUBLIC = 1;

    /**
     * 使用私钥操作
     */
    const USE_PRIVATE = 2;

    /**
     * 密钥配置
     * @var array
     */
    private $config = [];

    /**
     * RSA constructor.
     * @param array $config
     *
     * $config = ['public_key' => 'path', 'private_key' => 'path']
     *
     * @throws \Exception
     */
    public function __construct(array $config)
    {
        $this->config = $config;
        if (!isset($this->config['public_key'], $this->config['private_key'])) {
            throw new \Exception('密钥参数错误');
        }
    }

    /**
     * 获取公钥
     * @return null|resource
     */
    public function publicKey()
    {
        if (!is_file($this->config['public_key'])) {
            return null;
        }
        $content = file_get_contents($this->config['public_key']);

        return openssl_pkey_get_public($content);
    }

    /**
     * 获取私钥
     * @return null|resource
     */
    public function privateKey()
    {
        if (!is_file($this->config['private_key'])) {
            return null;
        }
        $content = file_get_contents($this->config['private_key']);

        return openssl_pkey_get_private($content);
    }

    /**
     * 加密数据
     * @param string $data
     * @param int $type
     * @return string
     */
    public function encrypt(string $data, int $type = self::USE_PRIVATE): string
    {
        if (self::USE_PRIVATE === $type) {
            $func = 'openssl_private_encrypt';
            $key = $this->privateKey();
        } else {
            $func = 'openssl_public_encrypt';
            $key = $this->publicKey();
        }

        $string = '';
        foreach (str_split($data, 117) as $chunk) {
            /** @var string $encryptData */
            $string .= ($func($chunk, $encryptData, $key) ? base64_encode($encryptData) : null);
        }

        return $string;
    }

    /**
     * 解密数据
     * @param string $data
     * @param int $type
     * @return string
     */
    public function decrypt(string $data, int $type = self::USE_PRIVATE): string
    {
        if (self::USE_PRIVATE === $type) {
            $func = 'openssl_private_decrypt';
            $key = $this->privateKey();
        } else {
            $func = 'openssl_public_decrypt';
            $key = $this->publicKey();
        }

        $string = '';
        foreach (str_split($data, 172) as $chunk) {
            /** @var string $decryptData */
            $string .= ($func(base64_decode($chunk), $decryptData, $key) ? $decryptData : null);
        }

        return $string;
    }
}
